package com.github.elliot.gatewaycenter.security.filters;

import com.github.elliot.gatewaycenter.function.PathMatchPredicate;
import com.github.elliot.gatewaycenter.security.service.SecurityUserDetailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.server.authorization.AuthorizationWebFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Collection;

@Slf4j
public class CustomAuthorizationWebFilter extends AuthorizationWebFilter {

    public CustomAuthorizationWebFilter(ReactiveAuthorizationManager<ServerWebExchange> authorizationManager) {
        super(authorizationManager);
    }

    @Component
    public static class PathBasedReactiveAuthorizationManager implements ReactiveAuthorizationManager<ServerWebExchange> {

        @Autowired
        private SecurityUserDetailService userDetailService;

        @Override
        public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, ServerWebExchange exchange) {
            String path = exchange.getRequest().getURI().getPath();
            return authentication.filter(Authentication::isAuthenticated)
                    .flatMapMany(auth -> Flux.fromIterable(auth.getAuthorities()))
                    .map(GrantedAuthority::getAuthority)
                    .any(pattern -> new PathMatchPredicate().test(path, pattern))
                    .map(AuthorizationDecision::new);
        }

    }

}
